﻿#include "DataAnalysis.h"

DataAnalysis::DataAnalysis()
{
    pState = new PCRState();
    table = new GuideTable();
}
DataAnalysis::~DataAnalysis(){
    if(table){
        delete table;
        table = nullptr;
    }
    if(pState){
        delete pState;
        pState = nullptr;
    }
}

void DataAnalysis::datao(QString outdir, int type){

    DebugLog::funcStart(DEBUG_CONTEXT, outdir);


    if(isc != "1"){
        DebugLog::funcEnd(DEBUG_CONTEXT, "自动导出未设置");
        return;
    }

    DebugLog::debug(DEBUG_CONTEXT, "数据计算");
    pState->init();


    DebugLog::debug(DEBUG_CONTEXT, "下游操作建议计算");
    table->init(pState);
    table->hide();


    DebugLog::debug(DEBUG_CONTEXT, "自动导出到Excel");
    if(outdir == ""){
        QSqlDatabase db = dbHelper::openConnection();
        QSqlQuery query(db);
        QString sql=QString("Select Name from ItemCode Where DicCode=100");
        query.exec(sql);
        while(query.next()){
            outdir = query.value("Name").toString();
        }
    }


    execDatao(outdir, type);
    DebugLog::funcEnd(DEBUG_CONTEXT);
}


QString DataAnalysis::execDatao(QString outdir, int type)
{
#ifdef Q_OS_ANDROID
    // SMB路径处理
    QString remoteDir = outdir;
    outdir = SMBManager::SMB2Local(remoteDir);
#endif

    DebugLog::funcStart(DEBUG_CONTEXT);



    // 我也不知道排序到安卓端为啥就不好使了……重新调整一下posiFilter的顺序
    // ..在PC端也不对了，还是重排吧...
    qSort(pState->posiList_filter.begin(), pState->posiList_filter.end());

    QVector<PosiName> posiList;
    for(char posi1 = 'A'; posi1 <= 'H'; posi1 ++){
        foreach(QString posi, pState->posiList_filter){
            if(posi.contains(posi1) && posi.size() == 2){
                posiList.append(posi);
            }
        }
        foreach(QString posi, pState->posiList_filter){
            if(posi.contains(posi1) && posi.size() == 3){
                posiList.append(posi);
            }
        }
    }
    pState->posiList_filter.clear(); pState->posiList_filter.swap(posiList);



    QString outpath;
    if(type == 0){      // 不知道导出文件名
        QDir dir;
        if (!dir.exists(outdir)) {
            dir.mkpath(outdir);     // 创建目录
        }
        QString currentTime = QDateTime::currentDateTime().toString("yyyy-MM-dd_HH-mm-ss");
        outpath = outdir + "/" + currentTime + ".xlsx";
    }else{

        QList<QString> dirList = outdir.split("/");
        QString dirName = "";
        for(int i = 0; i < dirList.size()-1; i ++){
            dirName.append(dirList[i] + "/");
        }
        QDir dir;
        if (!dir.exists(dirName)) {
            dir.mkpath(dirName); // 创建目录
        }

        outpath = outdir;
    }

    DebugLog::debug(DEBUG_CONTEXT, "ExportPath:" + outpath);

    QSqlDatabase db = dbHelper::openConnection();
    QSqlQuery query(db);

    // 创建xlsx文档
    QXlsx::Document xlsx;
    QFile file(outpath);
    if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
        QMessageBox::critical(nullptr, "Error", "Could not open file for writing:" + file.errorString());
        return "";
    }

    xlsx.addSheet("样本设置");
    xlsx.addSheet("原始数据");
    xlsx.addSheet("扩增数据");
    xlsx.addSheet("结果分析");


    DebugLog::debug(DEBUG_CONTEXT, "[样本设置]");

    xlsx.selectSheet("样本设置");       // =========================================== 样本设置

    xlsx.write(1,1,"仪器名称");         xlsx.write(1,2,"96-PCR");
    xlsx.write(2,1,"创建日期");         xlsx.write(2, 2, pState->experimentRunTime);
    xlsx.write(3,1,"实验名称");         xlsx.write(3, 2, pState->experimentName);
    xlsx.write(4,1,"实验结束时间");         xlsx.write(4, 2, pState->experimentFinishTime);

    xlsx.write(6, 1, "孔位");
    xlsx.write(6, 2, "样本名称");
    xlsx.write(6, 3, "样本类型");
    xlsx.write(6, 4, "荧光染料");
    xlsx.write(6, 5, "浓度");
    int lineIdx = 7;
    foreach(PosiName posi, pState->posiList_filter){
        foreach(ChannelName channel, pState->channelList_filter){
            if(!pState->sampleInfo_posi.contains(posi)){
                continue;
            }
            if(!pState->curveList.contains(CurveName(channel, posi))){
                continue;
            }
            xlsx.write(lineIdx, 1, pState->sampleInfo_posi[posi][0]);
            xlsx.write(lineIdx, 2, pState->sampleInfo_posi[posi][1]);
            xlsx.write(lineIdx, 3, pState->sampleInfo_posi[posi][2]);
            xlsx.write(lineIdx, 4, channel);
            xlsx.write(lineIdx, 5, pState->sampleInfo_posi[posi][3]);
            lineIdx ++;
        }

    }

    DebugLog::debug(DEBUG_CONTEXT, "[原始数据]");
    xlsx.selectSheet("原始数据");       // ============================================ 原始数据

    xlsx.write(1,1,"仪器名称");         xlsx.write(1,2,"96-PCR");
    xlsx.write(2,1,"创建日期");         xlsx.write(2, 2, pState->experimentRunTime);
    xlsx.write(3,1,"实验名称");         xlsx.write(3, 2, pState->experimentName);
    xlsx.write(4,1,"实验结束时间");         xlsx.write(4, 2, pState->experimentFinishTime);

    xlsx.write(6, 1, "孔位");
    xlsx.write(6, 2, "循环数");
    for(int i = 0; i < pState->channelList_filter.size(); i ++){
        xlsx.write(6, i+3, *(pState->channelList_filter.begin()+i));
    }

    lineIdx = 7;
    // 循环数
    for(int cycle = 1; cycle <= pState->cycleNum; cycle ++){
        // 孔位
        foreach(QString posi, pState->posiList_filter){
            xlsx.write(lineIdx, 1, posi);
            xlsx.write(lineIdx, 2, cycle);
            for(int i = 0; i < pState->channelList_filter.size(); i ++){
                QString channel = *(pState->channelList_filter.begin()+i);
                QString curveName = CurveName(channel, posi);
                if(!(pState->rawData.contains(curveName) && pState->rawData[curveName].size() > (cycle-1))){
                    continue;
                }
                double data = pState->rawData[curveName][cycle-1].y();
                xlsx.write(lineIdx, i+3, data);
            }
            lineIdx ++;
        }
    }
    for(int cycle = pState->cycleNum+1; cycle <= pState->cycleNum_ampl; cycle++){       // 循环数据不全时补位
        foreach(QString posi, pState->posiList_filter){
            xlsx.write(lineIdx, 1, posi);
            xlsx.write(lineIdx, 2, cycle);
            lineIdx ++;
        }
    }

    DebugLog::debug(DEBUG_CONTEXT, "[扩增数据]");
    xlsx.selectSheet("扩增数据");       // ============================================ 扩增数据

    xlsx.write(1,1,"仪器名称");         xlsx.write(1,2,"96-PCR");
    xlsx.write(2,1,"创建日期");         xlsx.write(2, 2, pState->experimentRunTime);
    xlsx.write(3,1,"实验名称");         xlsx.write(3, 2, pState->experimentName);
    xlsx.write(4,1,"实验结束时间");         xlsx.write(4, 2, pState->experimentFinishTime);

    xlsx.write(6, 1, "孔位");
    xlsx.write(6, 2, "循环数");
    xlsx.write(6, 3, "荧光染料");
    xlsx.write(6, 4, "Rn");
    xlsx.write(6, 5, "ΔRn");

    lineIdx = 7;
    foreach(QString channel, pState->channelList_filter){
        foreach(QString posi, pState->posiList_filter){
            QString curveName = CurveName(channel, posi);
            if(!pState->curveList.contains(CurveName(channel, posi))){
                continue;
            }
            int last_idx = 0;
            for(int i = 0; i < pState->modelList[curveName]->getFittedData().size(); i ++){

                if(pState->modelList[curveName]->getFittedData()[i].x() == 0){
                    continue;
                }

                xlsx.write(lineIdx, 1, posi);
                xlsx.write(lineIdx, 2, pState->modelList[curveName]->getFittedData()[i].x());
                last_idx = pState->modelList[curveName]->getFittedData()[i].x();
                xlsx.write(lineIdx, 3, channel);
                if((!pState->modelList.contains(curveName))){
                    lineIdx ++;
                    continue;
                }
                xlsx.write(lineIdx, 4, pState->modelList[curveName]->getFittedData()[i].y());
                xlsx.write(lineIdx, 5, pState->modelList[curveName]->getFittedData_delta()[i].y());

                lineIdx ++;
            }
            for(int cycle = last_idx + 1; cycle <= pState->cycleNum_ampl; cycle++){       // 循环数据不全时补位

                xlsx.write(lineIdx, 1, posi);
                xlsx.write(lineIdx, 2, cycle);
                xlsx.write(lineIdx, 3, channel);
                lineIdx ++;
            }


        }
    }

    DebugLog::debug(DEBUG_CONTEXT, "[结果分析]");
    xlsx.selectSheet("结果分析");       // ============================================ 结果分析

    xlsx.write(1,1,"仪器名称");         xlsx.write(1,2,"96-PCR");
    xlsx.write(2,1,"创建日期");         xlsx.write(2, 2, pState->experimentRunTime);
    xlsx.write(3,1,"实验名称");         xlsx.write(3, 2, pState->experimentName);
    xlsx.write(4,1,"实验结束时间");         xlsx.write(4, 2, pState->experimentFinishTime);

    xlsx.write(6,1,"孔位");
    xlsx.write(6,2,"样本名称");
    xlsx.write(6,3,"样本类型");
    xlsx.write(6,4,"荧光染料");
    xlsx.write(6,5,"Ct");
    xlsx.write(6,6,"浓度");
    xlsx.write(6,7,"浓度平均值");
    xlsx.write(6,8,"y轴截距");
    xlsx.write(6,9,"斜率");
    xlsx.write(6,10,"扩增效率(%)");
    xlsx.write(6,11,"R2");
    xlsx.write(6,12,"指数期斜率");
    xlsx.write(6,13,"指数期效率(%)");
    lineIdx = 7;
    foreach(PosiName posi, pState->posiList_filter){
        foreach(ChannelName channel, pState->channelList_filter){

            CurveName name = CurveName(channel, posi);
            if(!pState->curveList.contains(CurveName(channel, posi))){
                continue;
            }
            xlsx.write(lineIdx, 1, posi);
            if(pState->sampleInfo_posi.contains(posi))    xlsx.write(lineIdx, 2, pState->sampleInfo_posi[posi][1]);
            if(pState->sampleInfo_posi.contains(posi))    xlsx.write(lineIdx, 3, pState->sampleInfo_posi[posi][2]);
            if(pState->sampleInfo_posi.contains(posi))    xlsx.write(lineIdx, 4, channel);
            if(pState->modelList.contains(name))          xlsx.write(lineIdx, 5, pState->modelList[name]->getCt_relative());
            if(pState->concList.contains(name))           xlsx.write(lineIdx, 6, QString::number(pState->concList[name], 'f', 6));
            if(pState->avgConcList.contains(channel))     xlsx.write(lineIdx, 7, QString::number(pState->avgConcList[channel], 'f', 6));
            if(pState->standardLine.contains(channel))    xlsx.write(lineIdx, 8, pState->standardLine[channel][1]);
            if(pState->standardLine.contains(channel))    xlsx.write(lineIdx, 9, pState->standardLine[channel][0]);
            if(pState->E.contains(channel))               xlsx.write(lineIdx, 10, pState->E[channel]==0 ? 0 : (pState->E[channel]-1)*100);
            if(pState->R2.contains(channel))              xlsx.write(lineIdx, 11, pState->R2[channel]);
            if(pState->modelList.contains(name))          xlsx.write(lineIdx, 12, pState->modelList[name]->getSlope());
            if(pState->modelList.contains(name))          xlsx.write(lineIdx, 13, pState->modelList[name]->getEfficiency()==0 ? 0 : (pState->modelList[name]->getEfficiency()-1)*100);
            lineIdx ++;
        }
    }

    // 关闭文件
    if(xlsx.saveAs(outpath)){
        qDebug("导出成功");
    }else{
        qDebug("导出失败");
    }


    DebugLog::debug(DEBUG_CONTEXT, "[下游操作建议]");
    table->save(outpath);

    DebugLog::debug(DEBUG_CONTEXT, "导出报告结束");

#ifdef Q_OS_ANDROID
    DebugLog::debug(DEBUG_CONTEXT, "[安卓上传]");
    if(SMBManager::isSMBPath(remoteDir)){
        bool res = SMBManager::I().uploadFile(remoteDir + outpath.split("/").back(), outpath);
        if(res){
            qDebug("上传成功");
        }else{
            qDebug("上传失败");
        }
    }
    DebugLog::debug(DEBUG_CONTEXT, "安卓上传结束");
#endif
    file.close();

    DebugLog::funcEnd(DEBUG_CONTEXT);
    return outpath;

}
